feat(devx): pin the ported guard-main-checkout self-test, and stop --resync rewriting governed files - #7954
Merged
baozhoutao merged 1 commit intoSep 6, 2026
Conversation
…resync rewriting governed files `scripts/upstream-port-pin.json` covered only `scripts/`, so the verbatim cross-repo ports under `.claude/hooks/**` — this repo's densest concentration of copies from the same upstream, and the one directory whose drift history is four separate human catches (#5459, #5712, #5789, #6042) — had no drift gate at all. Two changes, in the order they have to happen: 1. `--resync` now REFUSES to rewrite a ported path on the governed surface unless `--rewrite-governed-file` is passed, naming the path, the surface it matched and the flag. The governed set is read from `check-governed-queue-guard.mjs` rather than re-listed. The CHECK path is untouched: a drifted governed port reds with no flag and no exemption. 2. `.claude/hooks/guard-main-checkout.selftest.sh` is registered against the upstream blob the pin already names, with 14 declared divergences and a one-sentence `why` each. The wiring test's `pinned ⊆ patrol.paths` assertion silently encoded "the ledger only pins the sweeper's unit". It is re-scoped to the patrol's own unit, and the claim that matters for entries outside it is asserted directly: no pinned file falls inside `lint.yml`'s ignore set, so the PR that drifts one is never the PR on which the gate does not run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013uAaxiwgYDybsTNV9xwa1M
baozhoutao
marked this pull request as ready for review
September 6, 2026 04:29
This was referenced Sep 6, 2026
baozhoutao
deleted the
claude/issue-7263-port-pin-hooks-and-governed-resync-guard
branch
September 6, 2026 04:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7263
scripts/upstream-port-pin.jsoncovered onlyscripts/, so the verbatim cross-repo ports under.claude/hooks/**— this repo's densest concentration of copies from one upstream, and the directory whose drift history is four separate human catches (#5459, #5712, #5789, #6042) — had no drift gate. Two changes, in the order they have to happen.1.
--resyncrefuses to rewrite governed surfaceRegistering a file EDITS nothing;
--resyncREWRITES one in place, from another repository's bytes. Only the second is a governed-surface act.--resyncnow refuses any ported path on the governed surface unless--rewrite-governed-fileis passed, naming the path, the surface it matched and the flag. The governed set is read fromgovernedPathsIninscripts/check-governed-queue-guard.mjs— the repo's own definition, reused rather than re-listed, so the two cannot disagree.The CHECK path is untouched. A drifted governed port reds with no flag and no exemption; two self-test rows pin exactly that, because a gate that went quiet on the surface with the worst drift history would be this mechanism inverted.
Measured on this branch, all three legs:
2. The first
.claude/**entry, and what re-deriving it actually measuredd63c8a2. Re-derived today:bf10debd5and the blob atd63c8a2are byte-identical for this file, so the pin's ref is not the reason the count moved.fix(hooks): read the edited path from the key the routed tool carries) landed after the port and rewrote the matrix — thenbpayhelper, the routed-tool drift arm, the matcher/known_path_keyspairing, the notebook verdict section, and the removal of the hole section that finding(hooks):guard-main-checkout.shnever readsnotebook_path, so everyNotebookEditis judged byCLAUDE_PROJECT_DIR— wrong in BOTH directions, though the matcher routes that tool to it #7260 pinned.So the entry is registered with 14 declared divergences, not 4, and 12 of them cover executable text. Each carries its one-sentence
why; twelve name #7686, two name the port itself (the provenance header, and the KNOWN HOLE re-pointing at this repo's own #7259 with upstream's number kept as a cross-reference). The gate's green line is exactly true and says what it verified:main(a4816a79d) the same file still differs by 102 lines (40 executable), two of them live and already tracked — the substring worktree hole (#7259, and PR #7749 is in flight on it) and the escape-hatch remedy sentence (#7775). The pin's singleupstream.refcannot see either. That, plus the drift table for the other seven hooks, is filed as #7953.Reverse verification
Mutated on disk, gate read, restored with
git checkout HEAD -- PATH, restore proved by blob hash (4844703e2a72bb…) and an emptygit diff HEADeach time. All three drift directions reached:87 passed→88 passed)ported-from-provenance-header#7259→#7258)hole-heading-repointedy.ts→z.ts)perlone-liner whose escaping silently matched nothing, exit 0); it was caught by counting the deleted and injected text on disk rather than by trusting the editor's exit code, and re-run.Wiring: one assertion re-scoped, one added
upstream-port-parity-wiring.test.tsassertedpinned ⊆ half-state-patrol.paths. That silently encoded "the ledger only ever pins the sweeper's unit" — true of the two entries that existed, not a property of the ledger — and it reds on the first entry outsidescripts/. It is re-scoped to the patrol's own unit in both directions, and the claim that matters for entries beyond it is now asserted directly: no pinned file falls insidelint.yml's ignore set, so the pull request that drifts a pinned file is never the one on which the gate does not run. That test carries a control leg — each ignore glob must recognise a file it exists to ignore — because the first version of its glob matcher matched nothing and passed.Serial note
mainas off10e49f36, deliberately not against that branch; when #7749 lands, divergenceshole-heading-repointed,hole-crossref-repointedand their neighbours need re-deriving, and the gate will say so loudly rather than quietly (expected its ported text exactly once, found 0).Gates
check-upstream-port-parity✓ … 3 ported file(s) match …(was 2)… --self-test✓ … 49 cases pass(was 37)scripts/__tests__(3 suites)Test Files 3 passed (3) · Tests 46 passed (46)pnpm type-check:scriptspnpm lint:root✖ 32 problems (0 errors, 32 warnings); the three changed files re-linted alone: 0 errors, 0 warningspnpm check:control-bytes✅ OK (scanned 6410 tracked text file(s))pnpm check:governed-queue-guardOK … 132 cases passcheck-governed-queue-guard --test(the 3 changed paths)✅ NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matched.check-changeset-presence✅ No source or published contract of a released package changed in this rangeRun at
4263ff3f4. No file under.claude/**is edited by this pull request — the ported file is registered, not touched.Generated by Claude Code